package com.oss.service.oss;

import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.oss.common.BaseResponse;
import com.oss.config.ThreadContext;
import com.oss.dto.dictionary.SelectDictionaryByTypeSetDto;
import com.oss.dto.oss.partnershare.PartnerSharePageDto;
import com.oss.dto.oss.purchasecourses.PurchaseCoursesPageDto;
import com.oss.dto.oss.student.*;
import com.oss.dto.user.UserAddDto;
import com.oss.dto.user.UserUpdateDto;
import com.oss.entity.oss.PurchaseCourses;
import com.oss.entity.oss.RechargeManage;
import com.oss.entity.oss.Student;
import com.oss.entity.oss.TradeManage;
import com.oss.entity.system.Dictionary;
import com.oss.entity.system.User;
import com.oss.enums.IsDeletedEnum;
import com.oss.mapper.oss.StudentMapper;
import com.oss.service.system.DictionaryService;
import com.oss.service.system.UserService;
import com.oss.util.DownloadUtil;
import com.oss.util.easyexcel.EasyExcelExportByTemplateUtil;
import com.oss.util.SnowFlakeUtil;
import com.oss.util.TemplatePathUtil;
import com.oss.vo.oss.partnershare.PartnerShareVO;
import com.oss.vo.oss.purchasecourses.PurchaseCoursesVO;
import com.oss.vo.oss.student.*;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.FileInputStream;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

/**
 * @author chengqiang
 */
@Service
public class StudentService extends ServiceImpl<StudentMapper, Student> {
    @Autowired
    UserService userService;
    @Autowired
    DictionaryService dictionaryService;
    @Autowired
    TemplatePathUtil templatePathUtil;
    @Autowired
    DownloadUtil downloadUtil;
    @Autowired
    PositionManageService positionManageService;
    @Autowired
    TradeManageService tradeManageService;
    @Autowired
    PurchaseCoursesService purchaseCoursesService;
    @Autowired
    PartnerShareService partnerShareService;
    @Autowired
    RechargeManageService rechargeManageService;

    /**
     * 获取查询wrapper
     * @param dto 入参dto
     * @return 返回wrapper对象
     */
    public LambdaQueryWrapper getWrapper(StudentPageDto dto) {
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
        wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(StringUtils.isNotBlank(dto.getWechatID()),Student::getWechatID, dto.getWechatID());
        wrapper.like(StringUtils.isNotBlank(dto.getName()),Student::getName, dto.getName());
        wrapper.eq(StringUtils.isNotBlank(dto.getWeMediaPlatform()),Student::getWeMediaPlatform, dto.getWeMediaPlatform());
        wrapper.eq(StringUtils.isNotBlank(dto.getAccount()),Student::getAccount, dto.getAccount());
        wrapper.like(StringUtils.isNotBlank(dto.getPlatformNockname()),Student::getPlatformNickname, dto.getPlatformNockname());
        if (dto.getRecommendedDateStart() != null){
            wrapper.ge(Student::getRecommendedDate,dto.getRecommendedDateStart());
        }
        if (dto.getRecommendedDateEnd() != null){
            wrapper.le(Student::getRecommendedDate,dto.getRecommendedDateEnd());
        }
        wrapper.orderByDesc(Student::getCreateTime);
        return wrapper;
    }

    public void export(StudentPageDto dto) throws Exception {
        LambdaQueryWrapper<Student> wrapper = getWrapper(dto);
        dto.setPageSize(1000000);
        IPage<StudentPageVO> page = selectByPage(dto);
        List<StudentExportVO> exportVOList  = page.getRecords().stream().map(entity->{
            StudentExportVO vo = new StudentExportVO();
            BeanUtils.copyProperties(entity,vo);
            return vo;
        }).collect(Collectors.toList());
        String outPath = templatePathUtil.getTempPath()+"tempExportData.xlsx";
        String templatePath = templatePathUtil.getStudentExportTemplatePath();
        EasyExcelExportByTemplateUtil.exportExcelByTemplate(outPath,templatePath,exportVOList);
        downloadUtil.downloadFile(new FileInputStream(outPath),"学员信息.xlsx");
        // 删除临时生成的文件
        //downloadUtil.deleteFileAndDir(outPath);
    }
    // 处理字典的数据
    public Map<String,String> getDictionaryMapByTypeCode(Map<String,List<Dictionary>> dicMap,String code){
        if (dicMap.containsKey(code) && CollectionUtils.isNotEmpty(dicMap.get(code))) {
            return dicMap.get(code).stream().collect(Collectors.toMap(Dictionary::getDicValue,Dictionary::getDicName,(v1,v2) -> v2));
        } else {
            return new HashMap<>();
        }
    }
    public IPage<StudentPageVO> selectByPage(StudentPageDto dto) {
        LambdaQueryWrapper<Student> wrapper = getWrapper(dto);
        IPage<Student> ipag = this.baseMapper.selectPage(new Page(dto.getPageNo(),dto.getPageSize()),wrapper);

        Map<String,String> userMap = new HashMap<>();
        // 自媒体平台字典值
        Map<String,String> weMediaPlatformDicMap = new HashMap<>();
        Map<String,String> accountLevelDicMap = new HashMap<>();
        Map<String,String> weMediaAccountDicMap = new HashMap<>();
        Map<String,String> vipServerDicMap = new HashMap<>();
        Map<String,String> recommendedDicMap = new HashMap<>();
        Map<String,String> studentManagerDicMap = new HashMap<>();
        Map<String,String> groupTypeDicMap = new HashMap<>();
        if (CollectionUtils.isNotEmpty(ipag.getRecords())) {
            // 获取创建人和修改人ID
            Set<String> ids = ipag.getRecords().stream().map(Student::getCreatorId).collect(Collectors.toSet());
            ids.addAll(ipag.getRecords().stream().map(Student::getUpdatorId).collect(Collectors.toSet()));
            userMap = userService.selectByIds(ids);
            List<String> codeSet = Arrays.asList("WeMediaPlatform","AccountLevel","WeMediaAccount","VipServer","Recommended","StudentManager","GroupType");
            SelectDictionaryByTypeSetDto selectDictionaryByTypeSetDto = new SelectDictionaryByTypeSetDto();
            selectDictionaryByTypeSetDto.setDicTypeCodeSet(codeSet);
            // 获取自媒体平台字典值 key = code , value = 字典列表
            Map<String,List<Dictionary>> dicMap = dictionaryService.selectDictionaryByTypeCodeSet(selectDictionaryByTypeSetDto);
            weMediaPlatformDicMap = getDictionaryMapByTypeCode(dicMap,"WeMediaPlatform");
            accountLevelDicMap = getDictionaryMapByTypeCode(dicMap,"AccountLevel");
            weMediaAccountDicMap = getDictionaryMapByTypeCode(dicMap,"WeMediaAccount");
            vipServerDicMap = getDictionaryMapByTypeCode(dicMap,"VipServer");
            recommendedDicMap = getDictionaryMapByTypeCode(dicMap,"Recommended");
            studentManagerDicMap = getDictionaryMapByTypeCode(dicMap,"StudentManager");
            groupTypeDicMap = getDictionaryMapByTypeCode(dicMap,"GroupType");
        }
        Map<String, String> finalUserMap = userMap;
        Map<String, String> finalWeMediaPlatformDicMap = weMediaPlatformDicMap;
        Map<String, String> finalAccountLevelDicMap = accountLevelDicMap;
        Map<String, String> finalGroupTypeDicMap = groupTypeDicMap;
        Map<String, String> finalVipServerDicMap = vipServerDicMap;
        Map<String, String> finalStudentManagerDicMap = studentManagerDicMap;
        Map<String, String> finalRecommendedDicMap = recommendedDicMap;
        Map<String, String> finalWeMediaAccountDicMap = weMediaAccountDicMap;
        return ipag.convert(entity->{
            StudentPageVO vo = new StudentPageVO();
            BeanUtils.copyProperties(entity,vo);
            vo.setCreatorName(finalUserMap.get(entity.getCreatorId()));
            vo.setUpdatorName(finalUserMap.get(entity.getUpdatorId()));
            vo.setCode(entity.getCode());
            vo.setAccountLevel(finalAccountLevelDicMap.get(entity.getAccountLevel()));
            vo.setGroupType(finalGroupTypeDicMap.get(entity.getGroupType()));
            vo.setWeMediaPlatform(finalWeMediaPlatformDicMap.get(entity.getWeMediaPlatform()));
            vo.setWeMediaAccount(finalWeMediaAccountDicMap.get(entity.getWeMediaAccount()));
            if (StringUtils.isNotBlank(entity.getVipServer()) && entity.getVipServer().startsWith("[") && entity.getVipServer().endsWith("]")) {
                List<String> list = JSON.parseArray(entity.getVipServer(),String.class);
                String vipServer = "";
                for (String item: list) {
                    vipServer = vipServer + finalVipServerDicMap.get(item) + ",";
                }
                vo.setVipServer(vipServer);
            }
            if (StringUtils.isNotBlank(entity.getStudentManager()) && entity.getStudentManager().startsWith("[") && entity.getStudentManager().endsWith("]")) {
                List<String> list = JSON.parseArray(entity.getStudentManager(),String.class);
                String studentManager = "";
                for (String item: list) {
                    studentManager = studentManager + finalStudentManagerDicMap.get(item) + ",";
                }
                vo.setStudentManager(studentManager);
            }
            if (StringUtils.isNotBlank(entity.getRecommended()) && entity.getRecommended().startsWith("[") && entity.getRecommended().endsWith("]")) {
                List<String> list = JSON.parseArray(entity.getRecommended(),String.class);
                String recommended = "";
                for (String item: list) {
                    recommended = recommended + finalRecommendedDicMap.get(item) + ",";
                }
                vo.setRecommended(recommended);
            }
            return  vo;
        });
    }

    /**
     * 统计手机号相同的个数
     * @param phone
     * @return
     */
    public long countPhone(String phone,String id){
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
        wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(Student::getPhone,phone);
        wrapper.ne(StringUtils.isNotBlank(id),Student::getId,id);
        return this.count(wrapper);
    }

    public BaseResponse add(StudentAddDto dto) {
        long count = this.countPhone(dto.getPhone(),null);
        if (count > 0){
           return BaseResponse.error("手机号已存在, 请联系管理员");
        } else {
            Student entity = new Student();
            BeanUtils.copyProperties(dto,entity);
            entity.setId(SnowFlakeUtil.getID());
            if (CollectionUtils.isNotEmpty(dto.getStudentManager())) {
                entity.setStudentManager(JSON.toJSONString(dto.getStudentManager()));
            }
            if (CollectionUtils.isNotEmpty(dto.getVipServer())) {
                entity.setVipServer(JSON.toJSONString(dto.getVipServer()));
            }
            if (CollectionUtils.isNotEmpty(dto.getRecommended())) {
                entity.setRecommended(JSON.toJSONString(dto.getRecommended()));
            }
            this.save(entity);
            // 账号(手机) 不存在时 , 才能新增
            if (userService.countByAccount(dto.getPhone()) == 0) {
                // 插入学员时 , 在插入一条用户数据 , 用来网页端登录使用 , 给一个默认角色(学员)
                UserAddDto userAddDto = new UserAddDto();
                userAddDto.setUserAccount(dto.getPhone());
                userAddDto.setUserPwd(dto.getLoginPassword());
                userAddDto.setUserName(dto.getName());
                // 学员角色
                userAddDto.setRoleIds(Stream.of("7326493909284941824").collect(Collectors.toSet()));
                userService.addUser(userAddDto);
            }
            return BaseResponse.success("操作成功");
        }
    }

    public BaseResponse<String> updateData(StudentUpdateDto dto) {
        long count = this.countPhone(dto.getPhone(),dto.getId());
        if (count > 0){
            return BaseResponse.error("手机号已存在");
        } else {
            Student entity = new Student();
            BeanUtils.copyProperties(dto,entity);
            if (CollectionUtils.isNotEmpty(dto.getStudentManager())) {
                entity.setStudentManager(JSON.toJSONString(dto.getStudentManager()));
            }
            if (CollectionUtils.isNotEmpty(dto.getVipServer())) {
                entity.setVipServer(JSON.toJSONString(dto.getVipServer()));
            }
            if (CollectionUtils.isNotEmpty(dto.getRecommended())) {
                entity.setRecommended(JSON.toJSONString(dto.getRecommended()));
            }
            this.updateById(entity);
            User user = userService.getByAccount(dto.getPhone());
            if (user != null) {
                UserUpdateDto userUpdateDto = new UserUpdateDto();
                userUpdateDto.setUserId(user.getUserId());
                userUpdateDto.setUserAccount(dto.getPhone());
                userUpdateDto.setUserPwd(dto.getLoginPassword());
                userUpdateDto.setUserName(dto.getName());
                if (dto.getStatus() != null) {
                    if (dto.getStatus() == 0) {
                        userUpdateDto.setUserStatus(2);
                    } else if(dto.getStatus() == 1){
                        userUpdateDto.setUserStatus(1);
                    }
                }
                // 学员角色
                userUpdateDto.setRoleIdList(Stream.of("7326493909284941824").collect(Collectors.toList()));
                userService.updateUser(userUpdateDto);
            }
            return BaseResponse.success("操作成功");
        }
    }

    public String delete(StudentGetByIDDto dto) {
        LambdaUpdateWrapper<Student> updateWrapper = new LambdaUpdateWrapper<>();
        updateWrapper.eq(Student::getId,dto.getId());
        updateWrapper.set(Student::getIsDeleted,IsDeletedEnum.YES.getFlag());
        this.update(updateWrapper);
        return "操作成功";
    }

    /**
     * 根据学员ID查询学员信息
     * @param studentIDs
     * @return 返回map key = 学员ID value = StudentVO
     */
    public Map<String,StudentVO> selectByIDs(Set<String> studentIDs) {
        if (CollectionUtils.isNotEmpty(studentIDs)){
            LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
            wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
            wrapper.in(Student::getId,studentIDs);
            List<Student> list = this.list(wrapper);
            Map<String,String> dictionaryMap = dictionaryService.getDictionaryMapByTypeCode("WeMediaPlatform");
            return list.stream().collect(Collectors.toMap(Student::getId,entity->{
                StudentVO vo = new StudentVO();
                BeanUtils.copyProperties(entity,vo);
                vo.setWeMediaPlatform(dictionaryMap.get(entity.getWeMediaPlatform()));
                return vo;
            }));
        } else {
            return new HashMap<>();
        }
    }
    /**
     * 根据学员ID查询学员信息
     * @param studentIDs
     * @return 返回map key = 学员ID value = StudentVO
     */
    public Map<String,String> selectStudentByIDs(Set<String> studentIDs) {
        if (CollectionUtils.isNotEmpty(studentIDs)){
            LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
            wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
            wrapper.in(Student::getId,studentIDs);
            List<Student> list = this.list(wrapper);
            Map<String,String> dictionaryMap = dictionaryService.getDictionaryMapByTypeCode("WeMediaPlatform");
            return list.stream().collect(Collectors.toMap(Student::getId,Student::getAccount,(v1,v2)->v2));
        } else {
            return new HashMap<>();
        }
    }

    public List<Student> getAll() {
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
        wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.orderByDesc(Student::getCreateTime);
        return this.list(wrapper);
    }

    /**
     * 根据合约 , 查询交易流水中的学员信息 , 标记哪些学员持有当前合约
     * @param dto
     * @return
     */
    public List<GetByInstrumentCodeStudentVO> getByInstrumentCode(ListByInstrumentCodeDto dto) {
        List<TradeManage> tradeList = tradeManageService.getByInstrumentCode(dto.getInstrumentCode());
        Set<String> studentIds = new HashSet<>();
        if (CollectionUtils.isNotEmpty(tradeList)){
            studentIds = tradeList.stream().map(TradeManage::getStudentID).collect(Collectors.toSet());
        }
        List<Student> studentList = getAll();
        Set<String> finalStudentIds = studentIds;
        return studentList.stream().map(entity->{
            GetByInstrumentCodeStudentVO vo = new GetByInstrumentCodeStudentVO();
            BeanUtils.copyProperties(entity,vo);
            if (finalStudentIds.contains(entity.getId())) {
                vo.setHoldCurrentInstrumentCode(true);
            } else {
                vo.setHoldCurrentInstrumentCode(false);
            }
            return vo;
        }).collect(Collectors.toList());
    }

    /**
     * 根据学员的账号 , 查询学员的ID
     * @param accountSet 账户集合
     * @return  返回map key = account value=ID
     */
    public Map<String, String> getByAccountSet(Set<String> accountSet) {
        if (CollectionUtils.isEmpty(accountSet)){
            return new HashMap<>();
        }
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
        wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.in(Student::getAccount, accountSet);
        wrapper.orderByDesc(Student::getCreateTime);
        List<Student> list = this.list(wrapper);
        if (CollectionUtils.isNotEmpty(list)){
            // 如果一个账户对应多个学员, 以后创建的那个为准
            return list.stream().collect(Collectors.toMap(Student::getAccount,Student::getId,(v1,v2)->v2));
        } else {
            return new HashMap<>();
        }
    }

    /**
     * 登录时 , 手机号作为账号登录
     * @param userAccount
     * @return
     */
    public Student getByUserAccount(String userAccount) {
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
        wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(Student::getPhone, userAccount);
        wrapper.orderByDesc(Student::getCreateTime);
        wrapper.last("limit 1");
        return this.getOne(wrapper);
    }

    /**
     * 通过场内账户(唯一的)查询学员信息
     * @param account
     * @return
     */
    public Student getByAccount(String account) {
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
        wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(Student::getAccount, account);
        wrapper.orderByDesc(Student::getCreateTime);
        wrapper.last("limit 1");
        return this.getOne(wrapper);
    }

    public StudentInfoVO getByPhone(StudentGetByPhoneDto dto) {
        StudentInfoVO returnVO = new StudentInfoVO();
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
        wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(Student::getPhone, dto.getPhone());
        Student entity = this.getOne(wrapper);
        if (entity != null){
            String studentID = entity.getId();
            BeanUtils.copyProperties(entity,returnVO);
            PurchaseCoursesPageDto purchaseCoursesPageDto = new PurchaseCoursesPageDto();
            purchaseCoursesPageDto.setPageNo(1);
            purchaseCoursesPageDto.setPageSize(10000);
            purchaseCoursesPageDto.setStudentID(studentID);
            IPage<PurchaseCoursesVO> purchaseCoursespage  = purchaseCoursesService.selectByPage(purchaseCoursesPageDto);
            if (CollectionUtils.isNotEmpty(purchaseCoursespage.getRecords())) {
                returnVO.setPurchaseCoursesList(purchaseCoursespage.getRecords());
            }
            Map<String,String> vipServerMap = dictionaryService.getDictionaryMapByTypeCode("VipServer");
            List<String> list = JSON.parseArray(entity.getVipServer(),String.class);
            String vipServer = "";
            for (String item: list) {
                vipServer = vipServer + vipServerMap.get(item) + ",";
            }
            returnVO.setVipServer(vipServer);
            List<RechargeManage> rechargeManageList = rechargeManageService.getByStudentID(studentID);
            if (CollectionUtils.isNotEmpty(rechargeManageList)) {
                BigDecimal unRecharge =  rechargeManageList.stream().map(item->{
                    return item.getUnRecharge() == null ? BigDecimal.ZERO : item.getUnRecharge();
                }).reduce(BigDecimal.ZERO, BigDecimal::add);
                returnVO.setUnRecharge(unRecharge);
            }

        }
        return returnVO;
    }

    public String createPhone() {
        int[] charts = {0,1,2,3,4,5,6,7,8,9};
        String phone = "111";
        Random random = new Random();
        // 随机8次
        for (int index=0;index<8;index++) {
            // 随机一个[0,9)之间的下标
            int randomIndex = random.nextInt(10);
            phone = phone+charts[randomIndex];
        }
        // 根据随机出来的手机号查询 , 这个手机号是否已存在
        LambdaQueryWrapper<Student> wrapper = new LambdaQueryWrapper<Student>();
        wrapper.eq(Student::getIsDeleted, IsDeletedEnum.NO.getFlag());
        wrapper.eq(Student::getPhone, phone);
        long count = this.count(wrapper);
        // 如果存在 , 重新随机一个手机号即可
        if (count > 0){
            phone = createPhone();
        }
        return phone;
    }

    public StudentDetailInfoVO getDetailById(String id) {
        Student entity = this.getById(id);
        StudentDetailInfoVO vo = new StudentDetailInfoVO();
        BeanUtils.copyProperties(entity,vo);
        if (StringUtils.isNotBlank(entity.getVipServer()) && entity.getVipServer().startsWith("[") && entity.getVipServer().endsWith("]")) {
            List<String> list = JSON.parseArray(entity.getVipServer(),String.class);
            vo.setVipServer(list);
        } else {
            vo.setVipServer(new ArrayList<>());
        }
        if (StringUtils.isNotBlank(entity.getStudentManager()) && entity.getStudentManager().startsWith("[") && entity.getStudentManager().endsWith("]")) {
            List<String> list = JSON.parseArray(entity.getStudentManager(),String.class);
            vo.setStudentManager(list);
        } else {
            vo.setStudentManager(new ArrayList<>());
        }
        if (StringUtils.isNotBlank(entity.getRecommended()) && entity.getRecommended().startsWith("[") && entity.getRecommended().endsWith("]")) {
            List<String> list = JSON.parseArray(entity.getRecommended(),String.class);
            vo.setRecommended(list);
        } else {
            vo.setRecommended(new ArrayList<>());
        }
        return vo;
    }

    public String mergeStudent(StudentMergeDto dto) {
        Student fromStudent = this.getById(dto.getFromStudentID());
        Student toStudent = this.getById(dto.getToStudentID());
        toStudent.setPhone(fromStudent.getPhone());
        toStudent.setLoginPassword(fromStudent.getLoginPassword());
        toStudent.setWechatID(fromStudent.getWechatID());
        toStudent.setName(fromStudent.getName());
        this.updateById(toStudent);
        fromStudent.setIsDeleted(IsDeletedEnum.YES.getFlag());
        this.updateById(fromStudent);
        return "操作成功";
    }
}
